package com.gugee.ins.data.analysis.service.impl;

import com.gugee.common.thread.ScheduleTemplate;
import com.gugee.ins.common.dal.ai.AiAnalysisClient;
import com.gugee.ins.common.dal.service.blogger.InsBloggerMainDao;
import com.gugee.ins.common.dal.service.brand.InsAiBloggerBrandDao;
import com.gugee.ins.common.dto.InsAiAnalysisBrand;
import com.gugee.ins.common.model.ai.InsBloggerBrand;
import com.gugee.ins.common.model.ai.InsBloggerBrandResponse;
import com.gugee.ins.common.model.mysql.brand.InsAiBloggerBrand;
import com.gugee.ins.data.analysis.config.InsAnalysisConfig;
import com.gugee.ins.data.analysis.service.InsAnalysisBrandService;
import com.gugee.ins.data.common.msg.InsBloggerMessage;
import com.xiguaji.boot.toolkit.JsonUtil;
import com.xiguaji.boot.toolkit.ThreadPoolUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;

/**
 * InsAnalysisBrandService 服务
 * @author Huangxin
 */
@Slf4j
@Service
public class InsAnalysisBrandServiceImpl implements InsAnalysisBrandService {

    /**
     * 配置
     */
    @Autowired
    InsAnalysisConfig insAnalysisConfig;

    /**
     * 线程调度
     */
    @Autowired
    ScheduleTemplate scheduleTemplate;

    /**
     * ai
     */
    @Autowired
    AiAnalysisClient aiAnalysisClient;

    /**
     * InsBloggerDao
     */
    @Autowired
    InsBloggerMainDao insBloggerMainDao;

    /**
     * insAiBloggerBrandDao
     */
    @Autowired
    InsAiBloggerBrandDao insAiBloggerBrandDao;

    /**
     * 线程池
     */
    ForkJoinPool forkJoinPool;

    /**
     * 线程名
     */
    private String workName = "insAnalysisBrand-worker";

    /**
     * 初始化线程池
     */
    @PostConstruct
    public void init() {
        forkJoinPool = ThreadPoolUtils.forkJoinPool(insAnalysisConfig.getInsAnalysisBrandCorePollSize(), workName);
        scheduleTemplate.attach(workName, forkJoinPool);
    }

    /**
     * 处理 分析播主分类 任务
     * @param insBloggerMessages
     */
    @Override
    public void handleAnalysisBrand(List<InsBloggerMessage> insBloggerMessages) {
        try {
            forkJoinPool.submit(() -> insBloggerMessages.parallelStream().forEach(insBloggerMessage -> {
                try {
                    // 分析品牌
                    analysisBrand(insBloggerMessage);
                } catch (Exception ex) {
                    log.error("insAnalysisBrand error. uid:{}, error :{}" ,
                            insBloggerMessage.getUid(),ex.getMessage());
                }
            })).get();
        } catch (Exception ex) {
            log.error("insAnalysisBrand thread error.  {}" ,  ex.getMessage());
        }
    }

    /**
     * 分析品牌
     *
     * @param insBloggerMessage
     */
    public void analysisBrand(InsBloggerMessage insBloggerMessage){
        long start = System.currentTimeMillis();
        long uid = insBloggerMessage.getUid();
        // 有文字才去爬取
        if(!StringUtils.isEmpty(insBloggerMessage.getUserName())){
            try{
                // 调用接口爬取
                InsBloggerBrandResponse insBloggerBrandResponse = aiAnalysisClient.getBrandByText(insBloggerMessage.getUserName());
                // 关联结果
                List<InsAiBloggerBrand> insAiBloggerBrands;
                // 用来存储在blogger_main的json里
                List<InsAiAnalysisBrand> insAiAnalysisBrands;

                long now = System.currentTimeMillis() / 1000;
                if(insBloggerBrandResponse != null
                        && insBloggerBrandResponse.getBrandItem() != null
                        && !insBloggerBrandResponse.getBrandItem().isEmpty()){
                    insAiBloggerBrands = new ArrayList<>(insBloggerBrandResponse.getBrandItem().size());
                    insAiAnalysisBrands = new ArrayList<>(insBloggerBrandResponse.getBrandItem().size());
                    for(InsBloggerBrand insBloggerBrand : insBloggerBrandResponse.getBrandItem()){
                        // 只有当brandLevel为1时才认为是该账户的品牌
                        if(insBloggerBrand != null && insBloggerBrand.getBrandLevel() == 1){
                            InsAiBloggerBrand insAiBloggerBrand = new InsAiBloggerBrand();
                            insAiBloggerBrand.setBid(insBloggerBrand.getId());
                            insAiBloggerBrand.setBrandName(insBloggerBrand.getBrandName());
                            insAiBloggerBrand.setEnName(insBloggerBrand.getEnName());
                            insAiBloggerBrand.setUid(uid);
                            insAiBloggerBrand.setCreateTime(now);
                            insAiBloggerBrands.add(insAiBloggerBrand);

                            InsAiAnalysisBrand insAiAnalysisBrand = new InsAiAnalysisBrand();
                            insAiAnalysisBrand.setBid(insBloggerBrand.getId());
                            insAiAnalysisBrand.setBrandName(insBloggerBrand.getBrandName());
                            insAiAnalysisBrand.setEnName(insBloggerBrand.getEnName());
                            insAiAnalysisBrands.add(insAiAnalysisBrand);
                            // todo 后面可能要增加更新品牌表的逻辑

                        }
                    }
                    // 特殊情况可能一条都没有
                    if(insAiBloggerBrands.isEmpty()){
                        addOneAiBloggerBrandsRecord(uid,insAiBloggerBrands,now);
                        insAiAnalysisBrands = null;
                    }
                }else{
                    insAiBloggerBrands = new ArrayList<>(1);
                    addOneAiBloggerBrandsRecord(uid,insAiBloggerBrands,now);
                    insAiAnalysisBrands = null;
                }
                // 更新
                updateBrand(uid,insAiBloggerBrands,insAiAnalysisBrands);
            }catch (Exception e){
                log.error("insAnalysisBrand ai analysis error,uid:{},msg:{}", uid,e.getMessage());
            }
        }

        if ((System.currentTimeMillis() - start) / 1000 > insAnalysisConfig.getInsAnalysisDebugTimeLimit()) {
            log.info("insAnalysisBrand uid:{} use time:{}s", uid,(System.currentTimeMillis() - start) / 1000);
        }
    }

    /**
     * 添加一条空记录
     * @param uid
     * @param insAiBloggerBrands
     * @param nowTime
     */
    private void addOneAiBloggerBrandsRecord(long uid,List<InsAiBloggerBrand> insAiBloggerBrands,long nowTime){
        InsAiBloggerBrand insAiBloggerBrand = new InsAiBloggerBrand();
        insAiBloggerBrand.setBid(null);
        insAiBloggerBrand.setBrandName(null);
        insAiBloggerBrand.setEnName(null);
        insAiBloggerBrand.setUid(uid);
        insAiBloggerBrand.setCreateTime(nowTime);
        insAiBloggerBrands.add(insAiBloggerBrand);
    }

    /**
     * 更新ai结果
     * @param uid
     * @param insAiBloggerBrands
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBrand(long uid,List<InsAiBloggerBrand> insAiBloggerBrands,List<InsAiAnalysisBrand> insAiAnalysisBrands){
        // 删除之前的记录
        insAiBloggerBrandDao.deleteByUid(uid);
        // 重新插入新记录
        insAiBloggerBrandDao.batchInsert(insAiBloggerBrands);
        // 更新标记位 同时补充添加额外冗余的json信息
        String brandJson = insAiAnalysisBrands == null ? null : JsonUtil.parseJson(insAiAnalysisBrands);
        insBloggerMainDao.updateAiBrand(uid,brandJson);
    }
}
